package wechat

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"main.go/global"
	"main.go/model/common"
	"main.go/model/common/response"
	"main.go/model/mall"
	"main.go/model/wechat"
	"main.go/utils"
)

type UserApi struct{}

var cusHttp = &utils.CusHttp{}

var lock sync.Mutex

var wechatTokenKey = "wechat_token_key"

var config = &wechat.TokenReq{
	Appid:  "wx2ad09d98ce53ed53",
	Secret: "486014e703956c64e7fdd526a4fa90af",
}

// func getWXSessionKey(code string) (data wechat.Code2sessionRes, err error) {
// 	appid := "你的AppID"
// 	secret := "你的AppSecret"
// 	urlStr := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appid, secret, code)
// 	result, err := cusHttp.Get(urlStr)
// 	if err != nil {
// 		return data, err
// 	}
// 	json.Unmarshal([]byte(result), &data)
// 	return data, nil
// }

func getWxToken(data *wechat.TokenReq) (out wechat.TokenRes, err error) {
	ctx := context.Background()
	lock.Lock()
	defer lock.Unlock()

	//先走redis读取数据
	redisData := global.EVA_REDIS.Get(ctx, wechatTokenKey)
	err = redisData.Err() // 检查Redis操作是否出错
	if err != nil {
		url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", data.Appid, data.Secret)
		result, err := cusHttp.Get(url)
		if err != nil {
			return out, err
		}
		if err = json.Unmarshal([]byte(result), &out); err != nil {
			return out, err
		}
		tokenTimeout := time.Duration(out.ExpiresIn) * time.Second
		marshal, err := json.Marshal(out)
		if err != nil {
			return out, err
		}
		err = global.EVA_REDIS.Set(ctx, wechatTokenKey, marshal, tokenTimeout).Err()
		if err != nil {
			global.EVA_LOG.Error("Redis Imp SetToken error ", zap.Error(err))
			return out, err
		}
		return out, nil
	}
	// 将从Redis获取的JSON字符串解析为TokenInfo结构体
	err = json.Unmarshal([]byte(redisData.Val()), &out)
	if err != nil {
		return out, err
	}
	return out, nil
}

func (a *UserApi) Login(c *gin.Context) {
	var l wechat.UserphonenumberReq
	err := c.ShouldBindJSON(&l)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = utils.Verify(l, utils.CodeVerify)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	tokenRes, err := getWxToken(config)
	if err != nil {
		global.EVA_LOG.Error("请求微信服务器 token 错误", zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}

	data := wechat.UserphonenumberReq1{
		Code: l.Code,
	}
	url := fmt.Sprintf("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%v", tokenRes.AccessToken)
	result, err := cusHttp.Post(url, data)
	if err != nil {
		global.EVA_LOG.Error("请求微信服务器 getuserphonenumber 错误", zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}

	var userphonenumber wechat.UserphonenumberRes
	if err := json.Unmarshal([]byte(result), &userphonenumber); err != nil {
		global.EVA_LOG.Error("解析微信手机号数据错误", zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}

	user, err := userService.IsExitMobile(&mall.MallUser{
		Mobile: userphonenumber.PhoneInfo.PhoneNumber,
	})
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			global.EVA_LOG.Error("手机号验证错误", zap.Error(err))
			response.FailWithMessage(err.Error(), c)
			return
		}
		user, err = userService.Create(&mall.MallUser{
			Mobile:   userphonenumber.PhoneInfo.PhoneNumber,
			Password: "123456",
		})
		if err != nil {
			global.EVA_LOG.Error("创建用户错误", zap.Error(err))
			response.FailWithMessage(err.Error(), c)
			return
		}
	}

	if *user.Enable {
		global.EVA_LOG.Error("登陆失败! 用户被禁止登录!")
		response.FailWithMessage("用户被禁止登录", c)
		return
	}
	token := utils.GenerateUUID()
	err = utils.SetToken(common.TokenInfo{
		UUID:   user.UUID,
		Token:  token,
		UserID: uint64(user.ID),
		Mobile: user.Mobile,
		Source: "app",
	})
	if err != nil {
		global.EVA_LOG.Error("登录失败", zap.Error(err))
		response.FailWithMessage("登录失败", c)
		return
	}

	response.OkWithDetailed(token, "登录成功", c)

}
